import * as THREE from "three";
import { NearestFilter, sRGBEncoding, TextureLoader, VideoTexture } from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader.js";
import { PLYLoader } from "three/examples/jsm/loaders/PLYLoader.js";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js";

export const LoaderType = {
  Texture: "Texture",
  GLTF: "GLTF",
  FBX: "FBX",
  Video: "Video",
  PLY: "PLY"
};

export default class Loader {
  constructor() {
    this.resources = {};
    this.total = 0;
    this.totalSuccess = 0;
    this.totalFail = 0;

    this.fileLoaded = null;
    this.loadEnd = null;

    const dracoLoader = new DRACOLoader();
    dracoLoader.setDecoderPath("draco/");
    const gltfLoader = new GLTFLoader();
    gltfLoader.setDRACOLoader(dracoLoader);
    this.gltfLoader = gltfLoader;
    this.fbxLoader = new FBXLoader();
    this.textureLoader = new TextureLoader();
    this.plyLoader = new PLYLoader();
  }

  onFileLoaded(callback) {
    this.fileLoaded = callback;
  }

  onLoadEnd(callback) {
    this.loadEnd = callback;
  }

  load(resources) {
    this.total += resources.length;
    if (resources) {
      this.resources = resources;
      for (const file of this.resources) {
        this.loadFile(file);
      }
    }
  }

  loadFile(file) {
    if (!file.type) {
      console.warn("缺少必要的文件类型！");
      return;
    } else {
      let loader;
      switch (file.type) {
        case LoaderType.GLTF:
          loader = this.gltfLoader;
          break;
        case LoaderType.FBX:
          loader = this.fbxLoader;
          break;
        case LoaderType.Texture:
          loader = this.textureLoader;
          break;
        case LoaderType.PLY:
          loader = this.plyLoader;
          break;
        default:
          loader = this.textureLoader;
      }
      loader.load(
        file.path,
        res => {
          this.loadSuccess(file, res);
        },
        undefined,
        res => {
          this.loadFail(file, res);
        }
      );
    }
  }

  loadSuccess(file, res) {
    this.totalSuccess++;
    const name = file.name;
    this.resources[name] = res;
    this.fileLoaded && this.fileLoaded(name, res);
    if (this.total === this.totalSuccess + this.totalFail) {
      this.loadEnd && this.loadEnd(this.resources);
    }
  }

  loadFail(file, res) {
    console.warn(`resource ${file.name} load fail`, res);
    this.totalFail++;
    if (this.total === this.totalSuccess + this.totalFail) {
      this.loadEnd(this.resources);
    }
  }
}